/*!
 * @文件名 logic_power.c
 *
 * @功能描述
 *  1.通过检测主机控制的FCD_EN信号,控制系统的上下电
 *	2.通过检测948的LVDS Lock信号,控制屏幕的显示与关闭
 *	3.通过硬件机制,保证系统可执行自断电操作,从而不需要进入stop模式
 */
#include "logic_public.h"
#include "fml_touch.h"

#define PERIOD_CHECK_WAKEUP		10		//检测FCD_EN信号的周期,10ms
#define PERIOD_CHECK_LVDS_LOCK	10		//检测LVDS lock信号的周期,10ms
//#define SUPPORT_BIST

static eNotifyEvent g_BattStatus = EN_NOTIFY_VOLTAGE_NORMAL;		//电源状态
static bool g_bPowerDown = true;		//false[已上电] 				true[已下电]
static bool g_bWakeUp = false;			//false[系统未唤醒]			true[系统已唤醒]
static bool bWakeUpStatusOld = false;
static bool bLockStatusOld = false;

task_t s_logic_check_lvds;				//周期检测LVDS lock信号的任务句柄
task_t s_logic_check_wakeup;			//周期检测Wakup信号的任务句柄(即主机FCD_EN信号)
extern void logic_parse_init(void);
extern void eol_mode_open(void);

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_up_step1
 * Description   : 检测到FCD_EN信号时,先给948等外围器件 供电,以便与解串器实现信号LOCK
 *
 * 供电关系说明:
 * 1.FCD_EN信号->SW_3V3_EN[H]->SW_3V3[H]: AD上拉有了,器件3.3v供电有了,948,max25512,pmic供上电
 * 2.
 *
 *END**************************************************************************/
static void logic_power_up_step1(void)
{
	//1.检测到FCD_EN信号->SW_3V3_EN[H]->SW_3V3[H]: AD上拉有了,器件3.3v供电有了,948,max25512,pmic供上电

	//2.拉高PON_HOLD自锁接管电源
	fml_gpio_write(OUT_PON_HOLD,true);

	//3.拉高LDO_1V2_EN,使能1.2v电压输出,948有用到1.2v
	fml_gpio_write(OUT_LDO_1V2_EN,true);

	//4.拉高3V3_TFT_EN,使能TFT_VDD输出,给TDDI供电
	fml_gpio_write(OUT_3V3_TFT_EN,true);

	//5.使能948 LVDS输出
	fml_gpio_write(OUT_LVDS_PDB,true);

#if 1
	//Read TP Version,must set TP_RST,TFT_RST,TFT_SYBYB
	//[1].拉高TFT_RST
	fml_gpio_write(OUT_TP_RST,true);

	//[2].拉高TFT_RST
	fml_gpio_write(OUT_TFT_RST,true);

	//[3].拉高TFT_SYBYB,TDDI退出Standby模式
	fml_gpio_write(OUT_TFT_SYBYB,true);
	cola_delay_ms(100);
	fml_touch_init();	//tp and 948 iic can not exist at the same time!!!!
	//logic_parse_init();
	eol_mode_open();
#endif
	//6.拉低TP_RST,将TDDI TP触摸复位
	fml_gpio_write(OUT_TP_RST,false);

	//7.拉低TFT_RST,将TDDI DP显示复位
	fml_gpio_write(OUT_TFT_RST,false);
	logWrite("logic_power_up_step1\r\n");
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_up_step2
 * Description   : 检测到LVDS Lock信号时,输出TFT相关电压,打开背光
 *
 *END**************************************************************************/
void logic_power_up_step2(void)
{
	//1.拉高TP_RST
	fml_gpio_write(OUT_TP_RST,true);

	//2.拉高TFT_RST
	fml_gpio_write(OUT_TFT_RST,true);

	//3.拉高TFT_SHLR,左右镜像控制
	fml_gpio_write(OUT_TFT_SHLR,true);

	//4.拉高TFT_SYBYB,TDDI退出Standby模式
	fml_gpio_write(OUT_TFT_SYBYB,true);

	//5.拉高TFT_DISP,使能显示
	fml_gpio_write(OUT_TFT_DISP,true);

	//6.拉低TFT_BIST,退出BIST测试模式
	fml_gpio_write(OUT_TFT_BIST,false);

	//7.拉高PMIC_EN,使能屏电压输出,具体输出还要写寄存器
	fml_gpio_write(OUT_PMIC_EN,true);

	//8.拉高BL_EN,使能MAX25512背光输出,具体输出还要写寄存器


	//10.找到master i2c这路设备
	fml_tft_init();
	cola_delay_ms(10);//必须加延时,否则后面i2c写入会出现失败情况!

	//11.按TFT规格书,i2c配置pmic输出电压:PAVDD,NAVDD,VGH,VGL
	fml_pmic_init();

	//12.i2c配置max25512背光输出
	cola_delay_ms(50);//

	fml_gpio_write(OUT_BL_EN,true);
	fml_max25512_init();

	//13.输出PWM背光控制(pwm输出放在最后,可避免闪屏!!)
	fml_pwm_init();

	fml_pwm_change_duty(0);
	logWrite("logic_power_up_step2\r\n");
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_down
 * Description   : 屏端系统下电函数
 *
 *END**************************************************************************/
static void logic_power_down(void)
{
	logWrite("logic_power_down\r\n");
	//1.关闭pwm输出
	fml_pwm_change_duty(0);
	fml_pwm_deinit();

	//6.拉低TFT_SYBYB,TDDI进入Standby模式
	fml_gpio_write(OUT_TFT_SYBYB,false);

	cola_delay_ms(50);

	//5.拉低TFT_DISP,关闭显示
	fml_gpio_write(OUT_TFT_DISP,false);

	cola_delay_ms(16);

	//2.拉低BL_EN,关闭MAX25512背光输出
	fml_gpio_write(OUT_BL_EN,false);

	//3.拉低PMIC_EN,关闭PMIC给屏的相关供电
	fml_gpio_write(OUT_PMIC_EN,false);

	//4.拉低TFT_BIST,退出BIST测试模式
	fml_gpio_write(OUT_TFT_BIST,false);

	//7.拉低TFT_RST,复位DP
	fml_gpio_write(OUT_TFT_RST,false);

	//8.拉低TP_RST,复位TP
	fml_gpio_write(OUT_TP_RST,false);

	//9.关闭948 LVDS输出
	fml_gpio_write(OUT_LVDS_PDB,false);

	//10.拉低3V3_TFT_EN,关闭TFT_VDD输出,给TDDI断电
	fml_gpio_write(OUT_3V3_TFT_EN,false);

	//11.拉低LDO_1V2_EN,关闭1.2v电压输出
	fml_gpio_write(OUT_LDO_1V2_EN,false);

	//12.拉低PON_HOLD,MCU关闭整个系统电源,包括自身供电[但电源异常时不能关闭电源]
	if(g_BattStatus == EN_NOTIFY_VOLTAGE_NORMAL)
		fml_gpio_write(OUT_PON_HOLD,false);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_task_check_lvds_lock
 * Description   : 周期检测948 LVDS Lock信号,控制TFT的显示与关闭
 *
 *END**************************************************************************/
static void logic_task_check_lvds_lock(void *arg, uint32_t event)
{
	(void)arg;
	(void)event;
#ifdef SUPPORT_BIST
	static bool bBistMode = false;
	static uint8_t style = 0;
	static int iPeriodCnt = 0;

#endif
	static int iDlyCnt = 0;

	if(g_bWakeUp == false)
		return;	//FCD_EN未接时不处理lock信号
	if(g_BattStatus != EN_NOTIFY_VOLTAGE_NORMAL)
		return; //电压异常时不处理lock信号
	bool bLockStatus = fml_gpio_read(IN_LVDS_UNLOCK);
	if(bLockStatusOld != bLockStatus)
	{
		iDlyCnt = 10;
#if 0
		if(bLockStatus)
			logWrite("detect bLockStatus = %d,signal match\r\n",bLockStatus);
		else
			logWrite("detect bLockStatus = %d,signal lost\r\n",bLockStatus);
#endif
		bLockStatusOld = bLockStatus;
	}
	if(iDlyCnt > 0)
	{
		iDlyCnt--;
		if(0 == iDlyCnt)
		{
			if(g_bPowerDown)
			{
				g_bPowerDown = false;
				logic_power_up_step2();
				fml_max25512_set_bklight_on(true);
				fml_pwm_change_duty(fml_get_host_pwm_value());
			}
#ifdef SUPPORT_BIST
			style = 0;
			iPeriodCnt = 0;
			if(!bLockStatus)
			{//检测lvds锁信号丢失
				if(g_BattStatus == EN_NOTIFY_VOLTAGE_NORMAL)
				{
					logWrite("enter bist\r\n");
					fml_gpio_write(OUT_TFT_BIST,true);
					fml_tft_BIST_clear();
					fml_tft_write_BIST_mode(style++);
					bBistMode = true;
				}
			}
			else
			{
				logWrite("exist bist\r\n");
				bBistMode = false;
				fml_gpio_write(OUT_TFT_BIST,false);
			}
#endif
		}
	}
#ifdef SUPPORT_BIST
	if(bLockStatus == false  && bBistMode)
	{
		iPeriodCnt+=PERIOD_CHECK_LVDS_LOCK;
		if(iPeriodCnt > 5000 && g_BattStatus == EN_NOTIFY_VOLTAGE_NORMAL)
		{//每隔5秒切换一次bist模式
			logWrite("iPeriodCnt=%d,bistMode=%d\r\n",iPeriodCnt,style);
			iPeriodCnt = 0;
			fml_tft_BIST_clear();
			fml_tft_write_BIST_mode(style);
			style++;
			if(style == 6) //remove filcker mode
				style++;
			if(style == 24)//切换到第24个模式再从0开始
				style=0;
		}
	}
#endif
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_task_check_wakeup_signal
 * Description   : 周期检测主机给过来的FCD_EN信号,控制系统的上下电
 *
 *END**************************************************************************/
static void logic_task_check_wakeup_signal(void *arg, uint32_t event)
{
	(void)arg;
	(void)event;
	static int iDlyCnt = 0;
	static bool bFirstPowerON = true;
	bool bWakeUpStatus = fml_gpio_read(IN_WAKEUP);
	bool bEnable = false;
	if(bWakeUpStatusOld != bWakeUpStatus)
	{
		iDlyCnt = 10;
		bWakeUpStatusOld = bWakeUpStatus;
	}
	if(iDlyCnt > 0)
	{
		iDlyCnt--;
		if(0 == iDlyCnt)
		{
			bEnable = true;
			logWrite("detect fcd_en=%d:",bWakeUpStatus);
		}
	}
	if(event > 0)
	{
		if((event & EN_NOTIFY_VOLTAGE_LOW) == EN_NOTIFY_VOLTAGE_LOW)
		{
			bEnable = true;
			bFirstPowerON = true;
			g_BattStatus = EN_NOTIFY_VOLTAGE_LOW;
			logWrite("detect bat low:");
		}
		if((event & EN_NOTIFY_VOLTAGE_HIGH) == EN_NOTIFY_VOLTAGE_HIGH)
		{
			bEnable = true;
			bFirstPowerON = true;
			g_BattStatus = EN_NOTIFY_VOLTAGE_HIGH;
			logWrite("detect bat high:");
		}
		if((event & EN_NOTIFY_VOLTAGE_NORMAL) == EN_NOTIFY_VOLTAGE_NORMAL)
		{
			bEnable = true;
			g_BattStatus = EN_NOTIFY_VOLTAGE_NORMAL;
			logWrite("detect bat normal:");
		}
	}

	if(bEnable)
	{
		if(bWakeUpStatus && g_BattStatus == EN_NOTIFY_VOLTAGE_NORMAL)
		{//上电
			if(g_bWakeUp == false)
			{
				logWrite("power up\r\n");
				g_bWakeUp = true;
				logic_power_up_step1();
				cola_timer_create(&s_logic_check_lvds, logic_task_check_lvds_lock, NULL);
				cola_timer_start(&s_logic_check_lvds, EN_COLA_TIMER_ALWAYS, PERIOD_CHECK_LVDS_LOCK);
			}
		}
		else
		{//下电
			if(g_bWakeUp || g_BattStatus != EN_NOTIFY_VOLTAGE_NORMAL)
			{//下电
				logWrite("power down\r\n");
				cola_timer_stop(&s_logic_check_lvds);
				cola_timer_delete(&s_logic_check_lvds);
				g_bWakeUp = false;
				g_bPowerDown = true;
				logic_power_down();
				//cola_delay_ms(200);
			}
		}
		if(bFirstPowerON)
		{
			bFirstPowerON = false;
			cola_delay_ms(3000);
		}
		else
		{
			cola_delay_ms(500);
		}
		bLockStatusOld = !fml_gpio_read(IN_LVDS_UNLOCK);
		logWrite("init bLockStatusOld=%d\r\n",bLockStatusOld);
	}
}

/*FUNCTION**********************************************************************
 *
 * Function Name : logic_power_init
 * Description   : 初始化电源管理检测任务
 *
 *END**************************************************************************/
void logic_power_init(void)
{
	logWrite("getSoftwareVersion:%s\r\n",getSoftwareVersion());
	bWakeUpStatusOld = !fml_gpio_read(IN_WAKEUP);
	cola_timer_create(&s_logic_check_wakeup, logic_task_check_wakeup_signal, NULL);
	cola_timer_start(&s_logic_check_wakeup, EN_COLA_TIMER_ALWAYS, PERIOD_CHECK_WAKEUP);
}
